package com.changzhi.common.aspect;

import com.alibaba.fastjson.JSON;
import com.changzhi.common.annotation.Verify;
import com.changzhi.common.enums.StatusCodeEnum;
import com.changzhi.common.exception.ServiceException;
import com.changzhi.common.util.IPUtil;
import com.changzhi.common.util.TokenUtil;
import com.changzhi.ldyl.model.dto.BaseDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * @Description:指定包下有@verify注解则打印日志及参数校验
 * @author: 小落
 * @date: 2020年09月07日
 */
@Slf4j
@Aspect
@Component
public class VerifyAspect {

    @Value("${spring.profiles.active}")
    private String env;

    @Before("execution(* com.changzhi.controller..*.*(..)) && @annotation(verify)")//切点表达式以及通知类型
    public void doBefore(JoinPoint joinPoint, Verify verify) {//通过joinPoint对象获取参数以及其他对象信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Object[] args = joinPoint.getArgs();
        if(args.length > 0){
            Object arg = args[0];
            if(arg instanceof BaseDto){
                BaseDto baseDto = (BaseDto) arg;
                //入参打印
                log.info("请求IP:{},请求URI:{},请求参数:{}", IPUtil.toIpAddr(request), request.getRequestURI(), JSON.toJSONString(baseDto));
                //时间戳校验
                if (verify.timestamp() && isTimeout(baseDto.getTimestamp(), TimeUnit.MINUTES.toMillis(10))) {
                    if(!"test".equals(env)){
                        throw new ServiceException(StatusCodeEnum.ERROR_TIME_OUT);
                    }
                }
                //登录状态token校验
                if(verify.login()){
                    //获取参数token值
                    if(StringUtils.isBlank(baseDto.getToken())){
                        throw new ServiceException("token不能为空");
                    }
                    baseDto.setUserId(TokenUtil.getUidByToken(baseDto.getToken()));
                }
            }else {
                throw new ServiceException("转换Dto异常");
            }
        }
    }

    /**
     * @param reqTime
     * @param timeout 超时时间 .单位:毫秒
     * @return true 已超时
     */
    public static boolean isTimeout(Long reqTime, long timeout) {
        if (reqTime == null) {
            reqTime = 0L;
        }
        reqTime = reqTime * 1000;
        return Math.abs((System.currentTimeMillis() - reqTime)) > timeout;
    }
}
